home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-15 / mou105.zip / MOU.C < prev    next >
C/C++ Source or Header  |  1991-03-15  |  25KB  |  819 lines

  1. /*****************************************************************************
  2.  * PROJECT:  Mouse routines with 'real' graphic cursor in text mode.
  3.  *****************************************************************************
  4.  * MODULE:  MOU.C
  5.  *****************************************************************************
  6.  * DESCRIPTION:
  7.  *   Main file for the mouse routines.
  8.  *
  9.  *****************************************************************************
  10.  * MODIFICATION NOTES:
  11.  *    Date     Version Author Comment
  12.  * 15-Mar-1991     1.04     dk   Added function to set mouse position.  From a
  13.  *                  suggestion by Gary Tepel.
  14.  * 17-Jan-1991     1.02     ta   Diffs sent to me from Tony Acero for middle
  15.  *                  mouse button support.
  16.  * 10-Jan-1991     1.01     dk   Made points variable global throughout module.
  17.  * 07-Jan-1991     1.00     dk   Fixed bugs and set up for release to Usenet.
  18.  * 26-Oct-1990     0.00     dk   Initial file.
  19.  *****************************************************************************
  20.  *
  21.  * DISCLAIMER:
  22.  *
  23.  * Programmers may incorporate any or all code into their programs,
  24.  * giving proper credit within the source. Publication of the
  25.  * source routines is permitted so long as proper credit is given
  26.  * to Dave Kirsch.
  27.  *
  28.  * Copyright (C) 1990, 1991 by Dave Kirsch.  You may use this program, or
  29.  * code or tables extracted from it, as desired without restriction.
  30.  * I can not and will not be held responsible for any damage caused from
  31.  * the use of this software.
  32.  *
  33.  * Author: a563@mindlink.UUCP  -or-  Zoid@cc.sfu.ca
  34.  *
  35.  *****************************************************************************
  36.  * This source works with Turbo C 2.0 and MSC 6.0 and above.
  37.  *****************************************************************************/
  38.  
  39. #ifdef __TURBOC__
  40. #pragma inline
  41. #endif
  42.  
  43. #include <stdio.h>
  44. #include <dos.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47.  
  48. #include "mou.h"
  49.  
  50. #define HEIGHT 16
  51.  
  52. word mousehidden = 0;           /* Is the mouse on? Additive flag */
  53. boolean mouseinstalled = FALSE; /* Is the mouse installed? */
  54.  
  55. volatile word mousex=0, mousey=0; /* Character position of mouse */
  56.  
  57. #ifndef __TURBOC__
  58. STATIC word _based(_segname("_CODE")) DGroupSeg;
  59. #endif
  60.  
  61. STATIC volatile word mbufin = 0, mbufout = 0; /* Mouse buffer pointers */
  62.  
  63. STATIC word mousefreeze = 0;           /* Is mouse frozen in place? */
  64.  
  65. STATIC MOUINFOREC mbuf[MOUSEBUFFERSIZE]; /* Mouse buffer */
  66.  
  67. /* Save information for non EGA/VGA */
  68. STATIC word oldword;
  69. STATIC word newword;
  70. STATIC boolean saved = FALSE;
  71. STATIC word oldmx, oldmy;
  72.  
  73. /* Save information for EGA/VGA displays */
  74. STATIC boolean egavga = FALSE; /* Do we have an EGA/VGA adapter? */
  75. STATIC byte savechars[3][3]; /* The saved characters we overwrote */
  76. STATIC dword mousecursormask[HEIGHT] =  {
  77.   0x00000000L,  /*0000000000000000*/
  78.   0x40000000L,  /*0100000000000000*/
  79.   0x60000000L,  /*0110000000000000*/
  80.   0x70000000L,  /*0111000000000000*/
  81.   0x78000000L,  /*0111100000000000*/
  82.   0x7c000000L,  /*0111110000000000*/
  83.   0x7e000000L,  /*0111111000000000*/
  84.   0x7f000000L,  /*0111111100000000*/
  85.   0x7f800000L,  /*0111111110000000*/
  86.   0x7f000000L,  /*0111111100000000*/
  87.   0x7c000000L,  /*0111110000000000*/
  88.   0x46000000L,  /*0100011000000000*/
  89.   0x06000000L,  /*0000011000000000*/
  90.   0x03000000L,  /*0000001100000000*/
  91.   0x03000000L,  /*0000001100000000*/
  92.   0x00000000L   /*0000000000000000*/
  93. };
  94.  
  95. STATIC dword mousescreenmask[HEIGHT] =  {
  96.   0x3fffffffL,  /*0011111111111111*/
  97.   0x1fffffffL,  /*0001111111111111*/
  98.   0x0fffffffL,  /*0000111111111111*/
  99.   0x07ffffffL,  /*0000011111111111*/
  100.   0x03ffffffL,  /*0000001111111111*/
  101.   0x01ffffffL,  /*0000000111111111*/
  102.   0x00ffffffL,  /*0000000011111111*/
  103.   0x007fffffL,  /*0000000001111111*/
  104.   0x003fffffL,  /*0000000000111111*/
  105.   0x007fffffL,  /*0000000001111111*/
  106.   0x01ffffffL,  /*0000000111111111*/
  107.   0x10ffffffL,  /*0001000011111111*/
  108.   0xb0ffffffL,  /*1011000011111111*/
  109.   0xf87fffffL,  /*1111100001111111*/
  110.   0xf87fffffL,  /*1111100001111111*/
  111.   0xfcffffffL   /*1111110011111111*/
  112. };
  113.  
  114. STATIC byte chardefs[32 * 9]; /* 9 character definitons. */
  115. STATIC word mousepx, mousepy; /* Mouse pixel coordinates */
  116.  
  117. STATIC boolean conditionalhidemouse = FALSE;
  118. STATIC word conx1, cony1, conx2, cony2;
  119.  
  120. STATIC word vseg; /* Segment of video ram. */
  121. STATIC word mcols, mrows;
  122. STATIC byte savevmode;
  123. STATIC word points;
  124.  
  125. STATIC word maxx, maxy;
  126.  
  127. STATIC boolean desqview = FALSE;
  128.  
  129. #define POKEATTRIB(x, y, a) pokeb(vseg, (y) * (mcols * 2) + ((x) << 1) + 1, a)
  130. #define PEEKATTRIB(x, y)    peekb(vseg, (y) * (mcols * 2) + ((x) << 1) + 1)
  131.  
  132. #define POINTS *((byte far *) 0x00000485)
  133. #define COLS *((byte far *) 0x0040004AL)
  134. #define ROWS *((byte far *) 0x00400084L)
  135.  
  136. #define DEFCHAR 0xd0
  137.  
  138. /*********************************************************************/
  139. /* Mon 07-Jan-1991 - dk                                              */
  140. /*                                                                   */
  141. /*  Plot the cursor on the screen, save background, draw grid, etc.  */
  142. /*                                                                   */
  143. /*********************************************************************/
  144. PRIVATE void LOCAL FAST plotegavgacursor(word func)
  145. {
  146. word off;
  147. word width, height, i, j;
  148. word disp;
  149. word x = 0, y = 0;
  150. static word lsavex = 0, lsavey = 0;
  151.  
  152.   switch (func) {
  153.     case 0 : /* erase grid, put back save info */
  154.       x = lsavex;
  155.       y = lsavey;
  156.       break;
  157.     case 1 : /* draw grid */
  158.       x = mousex;
  159.       y = mousey;
  160.       break;
  161.     case 2 : /* save grid */
  162.       lsavex = x = mousex;
  163.       lsavey = y = mousey;
  164.       break;
  165.   }
  166.  
  167.   width = mcols - x;
  168.   if (width > 3)
  169.     width = 3;
  170.   height = mrows - y;
  171.   if (height > 3)
  172.     height = 3;
  173.  
  174.   off = y * (mcols * 2) + x * 2;
  175.   disp = (mcols * 2) - width * 2;
  176.  
  177.   switch (func) {
  178.     case 0 : /* erase grid, put back save info */
  179.       for (i = 0; i < height; i++, off += disp)
  180.         for (j = 0; j < width; j++, off += 2)
  181.           pokeb(vseg, off, savechars[i][j]);
  182.       break;
  183.     case 1 : /* draw grid. */
  184.       for (i = 0; i < height; i++, off += disp)
  185.         for (j = 0; j < width; j++, off += 2)
  186.           pokeb(vseg, off, DEFCHAR + i * 3 + j);
  187.       break;
  188.     case 2 : /* save grid. */
  189.       for (i = 0; i < height; i++, off += disp)
  190.         for (j = 0; j < width; j++, off += 2)
  191.           savechars[i][j] = peekb(vseg, off);
  192.       break;
  193.   }
  194. }
  195.  
  196. PRIVATE void LOCAL FAST drawegavgacursor(void)
  197. {
  198. word off;
  199. word i, j;
  200. word s1, s2, s3;
  201. dword *defs;
  202. dword *masks;
  203. word shift;
  204. dword addmask;
  205.  
  206.   plotegavgacursor(2); /* Save current grid that is there. */
  207.  
  208.   /* Time for some assembler.  Program the EGA/VGA Sequencer and Graphics
  209.      Controller for direct access to the character definition tables.
  210.      Then read in the definitions for the characters we are changing, AND
  211.      the screen mask, then OR the cursor mask to them.  Then copy those
  212.      defintions into the location of the mouse cursor defintions
  213.      and set the Sequencer and Graphics Controller back to normal <whew!>.
  214.   */
  215.  
  216.   /* Program the Sequencer */
  217.  
  218.   asm pushf; /* Disable interrupts */
  219.   asm cli;
  220.   asm mov dx, 3c4h; /* Sequencer port address */
  221.   asm mov ax, 0704h; /* Sequential addressing */
  222.   asm out dx, ax;
  223.  
  224.   /* Program the Graphics Controller */
  225.   asm mov dx, 3ceh; /* Graphics Controller port address */
  226.   asm mov ax, 0204h; /* Select map 2 for CPU reads */
  227.   asm out dx, ax;
  228.   asm mov ax, 0005h; /* Disable odd-even addressing */
  229.   asm out dx, ax;
  230.   asm mov ax, 0406h; /* Map starts at A000:0000 (64K mode) */
  231.   asm out dx, ax;
  232.   asm popf;
  233.  
  234.   /* Ok, now we have direct access to the character defintion tables, copy
  235.      over the defintions for the characters we are changing */
  236.  
  237.   off = 0;
  238.   for (i = 0; i < 9; i += 3) { /* Grid is three characters high. */
  239.     s1 = ((byte *)savechars)[i    ] * 32;
  240.     s2 = ((byte *)savechars)[i + 1] * 32;
  241.     s3 = ((byte *)savechars)[i + 2] * 32;
  242.     for (j = 0; j < points; j++) {
  243.       off++; /* 4th byte, that we don't need. */
  244.       chardefs[off++] = peekb(0xa000, s3++);
  245.       chardefs[off++] = peekb(0xa000, s2++);
  246.       chardefs[off++] = peekb(0xa000, s1++);
  247.     }
  248.   }
  249.  
  250.   /* Ok, we've got the defintions for the characters that we are drawing the
  251.      cursor on.  AND the screen mask and OR the cursor mask to them, thereby
  252.      'drawing' the cursor.  Since the cursor is 16 pixels wide and 16 pixels
  253.      high, we have to save a 3 by 3 character grid where the mouse cursor is
  254.      going.  We use dwords (32 bits) to do the bit AND and OR.  This could
  255.      be made alot faster on a 386 by using 32 bit registers. */
  256.  
  257.   shift = mousepx % 8;
  258.   addmask = 0xff000000L << (8 - shift);
  259.  
  260.   masks = mousescreenmask;
  261.   defs = ((dword *)chardefs) + mousepy % points;
  262.   for (i = 0; i < HEIGHT; i++)
  263.     *defs++ &= (*masks++ >> shift) | addmask;
  264.  
  265.   masks = mousecursormask;
  266.   defs = ((dword *)chardefs) + mousepy % points;
  267.   for (i = 0; i < HEIGHT; i++)
  268.     *defs++ |= *masks++ >> shift;
  269.  
  270.   /* Ok, Everything is setup, now copy the modifed character definitions
  271.      to their new location. */
  272.  
  273.   asm mov dx, 3c4h; /* Sequencer port address */
  274.   asm mov ax, 0402h; /* CPU writes only to map 2 */
  275.   asm out dx, ax;
  276.  
  277.   off = 0;
  278.   for (i = 0; i < 9; i += 3) { /* Grid is three characters high. */
  279.     s1 = (DEFCHAR + i    ) * 32;
  280.     s2 = (DEFCHAR + i + 1) * 32;
  281.     s3 = (DEFCHAR + i + 2) * 32;
  282.     for (j = 0; j < points; j++) {
  283.       off++; /* 4th byte, that we don't need. */
  284.       pokeb(0xa000, s3++, chardefs[off++]);
  285.       pokeb(0xa000, s2++, chardefs[off++]);
  286.       pokeb(0xa000, s1++, chardefs[off++]);
  287.     }
  288.   }
  289.  
  290.   /* Ok, put the Sequencer and Graphics Controller back to normal */
  291.  
  292.   /* Program the Sequencer */
  293.   asm pushf; /* Disable interrupts */
  294.   asm cli;
  295.   asm mov dx, 3c4h; /* Sequencer port address */
  296.   asm mov ax, 0302h; /* CPU writes to maps 0 and 1 */
  297.   asm out dx, ax;
  298.   asm mov ax, 0304h; /* Odd-even addressing */
  299.   asm out dx, ax;
  300.  
  301.   /* Program the Graphics Controller */
  302.   asm mov dx, 3ceh; /* Graphics Controller port address */
  303.   asm mov ax, 0004h; /* Select map 0 for CPU reads */
  304.   asm out dx, ax;
  305.   asm mov ax, 1005h; /* Enable odd-even addressing */
  306.   asm out dx, ax;
  307.   asm sub ax, ax;
  308.   asm mov es, ax; /* Segment 0 */
  309.   asm mov ax, 0e06h; /* Map starts at B800:0000 */
  310.   asm mov bl, 7;
  311.   asm cmp es:[49h], bl; /* Get current video mode */
  312.   asm jne notmono;
  313.   asm mov ax, 0806h; /* Map starts at B000:0000 */
  314. notmono:
  315.   asm out dx, ax;
  316.   asm popf;
  317.  
  318.   /* Ok, now put the bytes on the screen */
  319.  
  320.   plotegavgacursor(1); /* Plot the new grid on the screen. */
  321. }
  322.  
  323. /*******************************************************/
  324. /* 27-Oct-1990 - dk                                    */
  325. /*                                                     */
  326. /*  This function checks for the presense of EGA/VGA.  */
  327. /*                                                     */
  328. /*******************************************************/
  329. PRIVATE boolean LOCAL FAST isegavga(void)
  330. {
  331.   asm mov ax, 1a00h; /* ROM BIOS video function 1ah -- Read Display Code */
  332.   asm int 10h;
  333.   asm cmp ah, 1ah; /* Is this call supported? */
  334.   asm je checkega; /* Not supported */
  335.   asm cmp bl, 7; /* VGA w/monochrome display? */
  336.   asm je isvga; /* Yup. */
  337.   asm cmp bl, 8; /* VGA w/color display? */
  338.   asm jne checkega; /* Nope */
  339. isvga:
  340.   return TRUE; /* EGA/VGA is installed */
  341. checkega:
  342.   asm mov ah, 12h; /* EGA BIOS function */
  343.   asm mov bl, 10h;
  344.   asm int 10h;
  345.   asm cmp bl, 10h; /* Is EGA BIOS present? */
  346.   asm jne isvga; /* There is an EGA in the system. */
  347.   return FALSE; /* Not EGA or VGA in system. */
  348. }
  349.  
  350. /************************************************/
  351. /* 26-Oct-1990 - dk                             */
  352. /*                                              */
  353. /*  Mouse handler -- called from mouse driver.  */
  354. /*                                              */
  355. /************************************************/
  356. PRIVATE void far mousehandler(void)
  357. /* This function is called whenever a button is pressed.  Do not call this
  358.    function directly!!
  359. */
  360. {
  361. register word conditionmask;
  362.  
  363.   /* Get our data segment */
  364.   asm push ds
  365. #ifdef __TURBOC__
  366.   asm push ax
  367.   asm mov ax, DGROUP
  368.   asm mov ds, ax
  369.   asm pop ax
  370. #else
  371.   asm mov ds, cs:DGroupSeg
  372. #endif
  373.  
  374.   asm mov conditionmask,ax
  375.  
  376.   if (!mousefreeze) {
  377.     /* save mouse info passed to us from driver */
  378.     asm mov mousex, cx
  379.     asm mov mousey, dx
  380.     asm mov mousepx, cx
  381.     asm mov mousepy, dx
  382.  
  383.     mousex /= 8; /* Characters are 8 pixels wide */
  384.     mousey /= points; /* Scale mousey down */
  385.  
  386.     /* See if the mouse has moved. */
  387.     if (conditionmask & MOUSEMOVE) {
  388.       if (saved) {
  389.         if (egavga)
  390.           plotegavgacursor(0);
  391.         else
  392.           POKEATTRIB(oldmx, oldmy, oldword);
  393.         saved = FALSE;
  394.       }
  395.  
  396.       if (!mousehidden && conditionalhidemouse) /* Check to see if we need to hide */
  397.         if (mousex >= conx1 && mousex <= conx2 &&
  398.             mousey >= cony1 && mousey <= cony2) {
  399.           mousehidden++;
  400.           conditionalhidemouse = FALSE;
  401.         }
  402.  
  403.       if (!mousehidden) {
  404.         if (egavga)
  405.           drawegavgacursor();
  406.         else {
  407.           oldword = PEEKATTRIB(mousex, mousey);
  408.       asm mov ax, oldword;    /* Prepare to rotate attrib byte */
  409.           asm and al, 0f7h; /* Clear high bit */
  410.           asm mov cl, 4   /* We want to rotate 4 bits */
  411.           asm rol al, cl  /* Rotate it */
  412.       asm mov newword, ax;
  413.  
  414.           POKEATTRIB(mousex, mousey, newword); /* Write out new mouse cursor */
  415.         }
  416.  
  417.         oldmx = mousex;
  418.         oldmy = mousey;
  419.         saved = TRUE;
  420.  
  421.       }
  422.     }
  423.   }
  424.  
  425.   /* Now, see if a mouse button was whacked */
  426.   if (conditionmask & ~MOUSEMOVE)
  427.     if (((mbufin + 1) % MOUSEBUFFERSIZE) == mbufout) { /* Buffer full? */
  428. #ifdef __TURBOC__
  429.       sound(1760); /* Make some noise. */
  430.       delay(10);
  431.       nosound();
  432. #endif
  433.     } else {
  434.       mbuf[mbufin].buttonstat = conditionmask & ~MOUSEMOVE;
  435.       mbuf[mbufin].cx = mousex;
  436.       mbuf[mbufin].cy = mousey;
  437.       mbuf[mbufin].shiftstate = peekb(0, 0x417); /* Get shift byte */
  438.       mbufin = (mbufin + 1) % MOUSEBUFFERSIZE;
  439.     }
  440.  
  441.   asm pop ds;
  442. }
  443.  
  444. /************************************/
  445. /* 26-Oct-1990 - dk                 */
  446. /*                                  */
  447. /*  Initialize the mouse routines.  */
  448. /*                                  */
  449. /************************************/
  450. void FAST MOUinit(void)
  451. {
  452. byte v;
  453.  
  454. #ifndef __TURBOC__
  455.   asm mov cs:DGroupSeg,ds   /* save for interrupt handler to use */
  456. #endif
  457.  
  458.   asm sub ax,ax;    /* Mouse driver function 0 -- reset and detect */
  459.   asm int 33h
  460.   asm mov mouseinstalled, AX;
  461.  
  462.   if (mouseinstalled) { /* If a mouse is installed then activate driver */
  463.  
  464.     mousefreeze++; /* Make sure handler doesn't do things, yet */
  465.  
  466.     asm mov ax,0F00h;
  467.     asm int 10h;
  468.     asm mov v,al;
  469.  
  470.     if (v == 7) {
  471.       vseg = 0xb000u;
  472.     } else {
  473.       vseg = 0xb800u;
  474.       v = 3;
  475.     }
  476.  
  477.     if (ROWS == 0) { /* No value, assume 80x25. */
  478.       mrows = 25;
  479.       mcols = 80;
  480.       points = 8;
  481.     } else {
  482.       mrows = ROWS + 1;
  483.       mcols = COLS;
  484.       points = POINTS;
  485.     }
  486.  
  487.     /* Check to see if we are running in DESQview.  If so, don't try to
  488.        use the 'true' EGA/VGA cursor (DV doesn't like it at ALL). */
  489.  
  490.     asm mov ax, 2b01h;
  491.     asm mov cx, 4445h;
  492.     asm mov dx, 5351h;
  493.     asm int 21h;
  494.  
  495.     asm cmp al, 0ffh;
  496.     asm je notdv;
  497.  
  498.     desqview = TRUE;
  499.  
  500. notdv:
  501.  
  502.     /* Do we have an EGA or VGA?  If so, and we are not in monochrome mode
  503.        and we are not in DESQview then setup to draw a 'true' mouse cursor
  504.        on an EGA/VGA */
  505.     egavga = isegavga() && vseg != 0xb000u && !desqview;
  506.  
  507.     if (egavga) {
  508.       /* We are going to use our 'true' mouse cursor and we need pixel
  509.          resolution, not character resolution from the mouse driver
  510.          (In text mode, the mouse driver only returns coordinates in multiples
  511.          of 8, which we don't want.  We want multiples of 1, i.e. pixel
  512.          resolution).  To get the mouse driver to return coordinates in pixel
  513.          resolution, we 'trick' it into thinking it's in graphics mode by
  514.          setting the low memory byte indicating mode to mode 6 (CGA 640x200x2).
  515.          Then we reset the mouse driver.  The mouse driver will get the video
  516.          mode then act as if it was in graphics mode, not text mode. */
  517.       savevmode = peekb(0x40, 0x49);
  518.       pokeb(0x40, 0x49, 6); /* Does this work ?!?!?!?!? */
  519.  
  520.       /* Reset driver for change in video mode to take effect. */
  521.       asm sub ax,ax
  522.       asm int 33h
  523.  
  524.       /* Now that we've tricked the mouse driver into a grapics mode thereby
  525.          causing it to give us pixel resolutions, put the old mode back. */
  526.       pokeb(0x40, 0x49, savevmode);
  527.     }
  528.  
  529.     /* Set up max x and y ranges. */
  530.  
  531.     maxx = mcols * 8 - 1; /* Pixels horizontally */
  532.     maxy = mrows * points - 1; /* Pixels vertically */
  533.  
  534.     asm mov dx,maxx     /* Pixels horizontally */
  535.     asm mov ax,7        /* mouse driver function 7 -- set max x range */
  536.     asm sub cx,cx       /* Minimum range */
  537.     asm int 33h
  538.  
  539.     asm mov dx,maxy     /* Pixels veritcally */
  540.     asm mov ax,8        /* mouse driver function 8 -- set max y range */
  541.     asm sub cx,cx       /* Minimum range */
  542.     asm int 33h
  543.  
  544.     /* Now install user routine */
  545.  
  546.     asm mov ax,cs
  547.     asm mov es,ax
  548.     asm mov dx, offset mousehandler
  549.     /* Setup up bits for calling routine */
  550. #ifdef __TURBOC__
  551.     _CX = LEFTBPRESS | LEFTBRELEASE | RIGHTBPRESS | RIGHTBRELEASE | MIDBPRESS |
  552.       MIDBRELEASE | MOUSEMOVE;
  553. #else
  554.     asm mov cx, LEFTBPRESS | LEFTBRELEASE | RIGHTBPRESS | RIGHTBRELEASE | MIDBPRESS | MIDBRELEASE | MOUSEMOVE;
  555. #endif
  556.     asm mov ax,12       /* Function 12 -- set user routine */
  557.     asm int 33h
  558.  
  559.     mousex = mousey = mousepx = mousepy = 0;
  560.     asm mov cx,mousepx     /* xcoord */
  561.     asm mov dx,mousepy     /* ycoord */
  562.     asm mov ax,4    /* mouse driver function 4 -- set mouse position */
  563.     asm int 33h
  564.  
  565.     MOUshow(); /* Call it twice just to make sure */
  566.  
  567.     mousefreeze--; /* Handler can get into business, now */
  568.   }
  569. }
  570.  
  571. /****************************/
  572. /* 26-Oct-1990 - dk         */
  573. /*                          */
  574. /*  Hide the mouse cursor.  */
  575. /*                          */
  576. /****************************/
  577. void FAST MOUhide(void)
  578. /* This function turns off the mouse cursor, the mouse still responds
  579.    to button presses */
  580. {
  581.   if (!mouseinstalled)
  582.     return;
  583.  
  584.   mousefreeze++; /* don't have the handler doing weird things */
  585.  
  586.   mousehidden++; /* indicate it's hidden now */
  587.  
  588.   if (saved) {
  589.     if (egavga)
  590.       plotegavgacursor(0);
  591.     else
  592.       POKEATTRIB(oldmx, oldmy, oldword);
  593.     saved = FALSE;
  594.   }
  595.  
  596.   mousefreeze--; /* reactivate handler */
  597. }
  598.  
  599. /****************************/
  600. /* 26-Oct-1990 - dk         */
  601. /*                          */
  602. /*  Show the mouse cursor.  */
  603. /*                          */
  604. /****************************/
  605. void FAST MOUshow(void)
  606. {
  607.   if (!mouseinstalled)
  608.     return;
  609.  
  610.   mousefreeze++; /* don't have the handler doing weird things */
  611.  
  612.   /* Just in case we were in a conditionalhide */
  613.   if (conditionalhidemouse) {
  614.     /* We were about to conditional hide, but we didn't, don't reactive
  615.        mouse cursor. */
  616.     conditionalhidemouse = FALSE;
  617.     mousefreeze--; /* Reactivate handler */
  618.     return;
  619.   }
  620.  
  621.   if (mousehidden)
  622.     mousehidden--;
  623.   else {
  624.     mousefreeze--; /* Reactivate handler */
  625.     return;  /* It isn't hidden! */
  626.   }
  627.  
  628.   if (mousehidden) {
  629.     mousefreeze--; /* reactivate handler */
  630.     return; /* still hidden! */
  631.   }
  632.  
  633.   /* Draw mouse cursor */
  634.  
  635.   if (egavga)
  636.     drawegavgacursor();
  637.   else {
  638.     oldword = PEEKATTRIB(mousex, mousey);
  639.     asm mov ax, oldword;  /* Prepare to rotate attrib byte */
  640.     asm and al, 0f7h; /* Clear high bit */
  641.     asm mov cl, 4   /* We want to rotate 4 bits */
  642.     asm rol al, cl  /* Rotate it */
  643.     asm mov newword, ax;
  644.  
  645.     POKEATTRIB(mousex, mousey, newword); /* Write out new mouse cursor */
  646.   }
  647.  
  648.   oldmx = mousex;
  649.   oldmy = mousey;
  650.   saved = TRUE;
  651.  
  652.   mousefreeze--; /* Reactivate handler */
  653. }
  654.  
  655. /*************************************************************/
  656. /* 27-Oct-1990 - dk                                          */
  657. /*                                                           */
  658. /*  Returns true if there is something in the mouse buffer.  */
  659. /*                                                           */
  660. /*************************************************************/
  661. boolean FAST MOUcheck(void)
  662. {
  663.   return mbufin != mbufout;
  664. }
  665.  
  666. /**************************************************************/
  667. /* 26-Oct-1990 - dk                                           */
  668. /*                                                            */
  669. /*  Take a copy of the mouse event at the head of the queue.  */
  670. /*                                                            */
  671. /**************************************************************/
  672. void FAST MOUpreview(MOUINFOREC *mouinforec)
  673. {
  674.   if (!mouseinstalled)
  675.     return;
  676.  
  677.   if (mbufin != mbufout) /* if something is in buffer */
  678.     *mouinforec = mbuf[mbufout];
  679.   else {
  680.     /* Nothing to pull, just report mouse position */
  681.     mouinforec -> cx = mousex;
  682.     mouinforec -> cy = mousey;
  683.     mouinforec -> buttonstat = 0;
  684.     mouinforec -> shiftstate = peekb(0, 0x417);
  685.   }
  686. }
  687.  
  688. /****************************************************************/
  689. /* 26-Oct-1990 - dk                                             */
  690. /*                                                              */
  691. /*  Get (and remove) the mouse event at the head of the queue.  */
  692. /*                                                              */
  693. /****************************************************************/
  694. void FAST MOUget(MOUINFOREC *mouinforec)
  695. {
  696.   if (!mouseinstalled)
  697.     return;
  698.  
  699.   if (mbufin != mbufout) { /* if something is in buffer */
  700.     if (mouinforec != NULL)
  701.       *mouinforec = mbuf[mbufout];
  702.     mbufout = (mbufout + 1) % MOUSEBUFFERSIZE;
  703.   } else {
  704.     /* Nothing to pull, just report mouse position */
  705.     mouinforec -> cx = mousex;
  706.     mouinforec -> cy = mousey;
  707.     mouinforec -> buttonstat = 0;
  708.     mouinforec -> shiftstate = peekb(0, 0x417);
  709.   }
  710. }
  711.  
  712. /**************************************/
  713. /* 26-Oct-1990 - dk                   */
  714. /*                                    */
  715. /*  Deinitialize the mouse routines.  */
  716. /*                                    */
  717. /**************************************/
  718. void FAST MOUdeinit(void)
  719. {
  720.   if (!mouseinstalled)
  721.     return;
  722.  
  723.   MOUhide();
  724.  
  725.   asm sub ax,ax
  726.   asm int 33h
  727. }
  728.  
  729. /**************************************************/
  730. /* 26-Oct-1990 - dk                               */
  731. /*                                                */
  732. /*  Returns the bits for the button status info.  */
  733. /*                                                */
  734. /**************************************************/
  735. word FAST MOUbuttonstatus(void)
  736. {
  737. word buts;
  738.  
  739.   if (!mouseinstalled)
  740.     return 0;
  741.  
  742.   asm mov ax,3
  743.   asm int 33h
  744.   asm mov buts,bx
  745.   return buts;
  746. }
  747.  
  748. /************************************************************************/
  749. /* 26-Oct-1990 - dk                                                     */
  750. /*                                                                      */
  751. /*  Hide the mouse *if* it enters a certain screen area, automatically. */
  752. /*                                                                      */
  753. /************************************************************************/
  754. void FAST MOUconditionalhide(int x1, int y1, int x2, int y2)
  755. {
  756.   if (!mouseinstalled)
  757.     return;
  758.  
  759.   mousefreeze++; /* hold the handler */
  760.  
  761.   if (mousehidden) {
  762.     mousefreeze--; /* reactivate handler */
  763.     return; /* already hidden! */
  764.   }
  765.  
  766.   conditionalhidemouse = TRUE;
  767.  
  768.   x1 -= 2;
  769.   if (x1 < 0)
  770.     x1 = 0;
  771.   y1 -= 2;
  772.   if (y1 < 0)
  773.     y1 = 0;
  774.   x2 += 2;
  775.   y2 += 2;
  776.  
  777.   conx1 = x1;
  778.   cony1 = y1;
  779.   conx2 = x2;
  780.   cony2 = y2;
  781.  
  782.   if (mousex >= conx1 && mousex <= conx2 &&
  783.       mousey >= cony1 && mousey <= cony2) {
  784.     conditionalhidemouse = FALSE; /* We've already hidden it */
  785.     MOUhide(); /* turn it off now if it's there. */
  786.   }
  787.  
  788.   mousefreeze--;
  789. }
  790.  
  791. /*********************************************************/
  792. /* Fri 15-Mar-1991 - dk                  */
  793. /*                             */
  794. /*  Set the mouse cursor to a specific screen position.  */
  795. /*                             */
  796. /*********************************************************/
  797. void FAST MOUsetpos(word x, word y)
  798. {
  799.   if (!mouseinstalled)
  800.     return;
  801.  
  802.   mousefreeze++;
  803.  
  804.   MOUhide();
  805.  
  806.   mousex = x;
  807.   mousey = y;
  808.   mousepx = mousex * 8;
  809.   mousepy = mousey * points;
  810.   asm mov cx, mousepx    /* xcoord */
  811.   asm mov dx, mousepy    /* ycoord */
  812.   asm mov ax, 4     /* mouse driver function 4 -- set mouse position */
  813.   asm int 33h
  814.  
  815.   MOUshow();
  816.  
  817.   mousefreeze--;
  818. }
  819.